package IC.SymbolTable;

public class MethodSymbolTable extends BlockSymbolTable  
{

	private boolean isStatic;
	
	

	public MethodSymbolTable(String id, ClassSymbolTable parent) throws SemanticError 
	{
		
		super(parent);
		this.symTableId = id;
		this.isStatic = (parent.lookupMethodSymbolInCurrScope(id)).isStaticMethod();
		this.stt = symbolTableType.METHOD;
	}




	public void setReturnParamSymbol(String typeName,int line) throws SemanticError
	{
		this.varEntries.put("_retParam", new ReturnParamSymbol("_retParam", typeName,line));
	}


	public ReturnParamSymbol getReturnParamSymbol() throws SemanticError
	{
		return (ReturnParamSymbol) lookupSymbolInCurrScopeMethod("_retParam");
	}

	
	 public void addformalParamSymbol(String name, String typeName,int line) throws SemanticError{
		    this.varEntries.put(name, new formalParamSymbol(name, typeName,line));
 }
	

	public VariableSymbol lookupSymbolInCurrScopeMethod (String id)
	{
		if (varEntries == null)
		{
			return null;			
		}

		return  varEntries.get(id);
	}
	
	
	
	public boolean isDeclaredAlreadyInCurrScopeMethod(String symId)
	{
		if(varEntries.containsKey(symId))
		{
			return true;
		}

		return false;
	}
	
	public boolean isDeclaired(String id)
	{
		boolean b = false;
		if (varEntries.containsKey(id))
		{
			return true;
		}
		
		//TODO
		if (isStatic)
		{
			return false;
		}
		if (parentSymbolTable != null)
		{
			b= ((ClassSymbolTable) parentSymbolTable).isDeclaredInThisOrSuperClass(id, 'f');
		}
		
		return b;
	}
	
	
	public VariableSymbol lookupSymbol (String id)
	{
		VariableSymbol sym = varEntries.get(id);

		
		if ((sym == null))
		{
			
			if (this.isStatic) // the method to which this symbol table belongs to is a static method
			{ 
				
				return null;
			}

			else    // it is a virtual method, continue recursive search
			{
				sym = (VariableSymbol) ((ClassSymbolTable) parentSymbolTable).lookupSymbol(id);
			}

		}

		return sym;

	}



	public String toString()
	{
		String str = "Method Symbol Table: "+ this.getId();


		// print list of symbols (parameters and local variables)
		String formalparamsListStr = "";
		String localVarsListStr = "";


	
		for(VariableSymbol vs: varEntries.values())

		{
			
			if (vs.getKind() == Kind.FORMALPARAM){ // parameter case
				formalparamsListStr += "\n\tParameter: "+vs.getType().getName()+" "+vs.getId();
			
			} 
			else if (vs.getKind() != Kind.RETURNPARAM){ // local variable case
				localVarsListStr += "\n\tLocal variable: "+vs.getType().getName()+" "+vs.getId();
			}
		}

		str += formalparamsListStr+localVarsListStr;


		// print list of children tables (blocks only)

		String path = "statement block in "+this.getId();

		if (!childrenSymbolTables.isEmpty()){
			str += "\nChildren tables: ";
			for(SymbolTable st: childrenSymbolTables)
				str += path+", ";
			str = str.substring(0, str.length()-2);
		}
		str += "\n\n";

		for(SymbolTable st: childrenSymbolTables){
			str += ((BlockSymbolTable)st).toString(this.getId()); // in BlockSymbolTable
		}

		return str;
	}



}




